#pragma once
#include "Common.h"
#include "Symbol.h"

// Intermediate code

#define VARIABLE_DATA_SIZE 0x1000

// Value of enums equal to size in bytes
enum VARIABLE_TYPE
{
	VT_INT8,
	VT_INT16,
	VT_INT32,
	VT_INT64,

	VT_UINT8,
	VT_UINT16,
	VT_UINT32,
	VT_UINT64,

	VT_FLOAT32,
	VT_FLOAT64,

	VT_BITS8,
	VT_BITS16,
	VT_BITS32,
	VT_BITS64

	// All values beyond are indicies to Symbol table (typedefs/structs)
};

static const UInt variableTypeSizes[] = {1, 2, 4, 8, 1, 2, 4, 8, 4, 8, 1, 2, 4, 8};

enum VARIABLE_MODIFIER
{
	VM_CONST
};

struct Variable
{
	struct Symbol* symbol;
	enum VARIABLE_TYPE type;
	Int32 extra; // Extra data for final code gen stage
};

// Subclasses of Variable

struct Bits8Variable
{
	UInt8 initialValue;
};

struct Bits16Variable
{
	UInt16 initialValue;
};

struct Bits32Variable
{
	UInt32 initialValue;
};

struct Int8Variable
{
	Int8 initialValue;
};

struct Int16Variable
{
	Int16 initialValue;
};

struct Int32Variable
{
	Int32 initialValue;
};

struct UInt8Variable
{
	UInt8 initialValue;
};

struct UInt16Variable
{
	UInt16 initialValue;
};

struct UInt32Variable
{
	UInt32 initialValue;
};

struct UInt64Variable
{
	UInt64 initialValue;
};

struct Float32Variable
{
	Float32 initialValue;
};

struct Float64Variable
{
	Float64 initialValue;
};

#define PSUB_VARIABLE(V, SUB_STRUCT)\
	((SUB_STRUCT*)(((Int8*)(V)) + sizeof(struct Variable)))


#define ADD_TEMPVARIABLE(VAR_STRUCT, VAR_TYPE)\
	ADD_VARIABLE(VAR_STRUCT, VAR_TYPE, NULL)

#define ADD_VARIABLE(VAR_STRUCT, VAR_TYPE, SYMBOL)\
	variables;\
	variables->symbol = SYMBOL;\
	variables->extra = 0;\
	variables->type = VAR_TYPE;\
	variables = (struct Variable*)((Int8*)variables) + (sizeof(VAR_STRUCT) + sizeof(struct Variable));\

extern UInt8 variableData[VARIABLE_DATA_SIZE];
extern struct Variable* variables;
